{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4.1 Geometries in 2D\n",
    "\n",
    "We have to import the `SplineGeometry` class from the `geom2d` module to be able to generate two-dimensional geometries. After importing the module we can create a new `SplineGeometry`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import netgen.gui\n",
    "%gui tk\n",
    "from netgen.geom2d import SplineGeometry\n",
    "geo = SplineGeometry()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can use one the predefined objects (Rectangle,Circle) or generate our own geometry with lines or rational splines of 2nd order.\n",
    "\n",
    "## Predefined geometries\n",
    "First we use the predefined ones and add a rectangle and a circle to our geometry with the boundary conditions `rectangle` and `circle`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "geo.AddRectangle((-1,-1),(1,1),bc=\"rectangle\")\n",
    "geo.AddCircle((0,0),0.5,bc=\"circle\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "ngmesh = geo.GenerateMesh()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To get a proper geometry we have to set domain numbers for the domain on the left side of the curve and for the one in its right side. In this case the curves are parametrized in a mathematical positive sense.\n",
    "Additionally we can use `SetMaterial` to identify the domains with names."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "geo = SplineGeometry()\n",
    "geo.AddRectangle(p1=(-1,-1),\n",
    "                 p2=(1,1),\n",
    "                 bc=\"rectangle\",\n",
    "                 leftdomain=1,\n",
    "                 rightdomain=0)\n",
    "geo.AddCircle(c=(0,0),\n",
    "              r=0.5,\n",
    "              bc=\"circle\",\n",
    "              leftdomain=2,\n",
    "              rightdomain=1)\n",
    "geo.SetMaterial (1, \"outer\")\n",
    "geo.SetMaterial (2, \"inner\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "geo.SetDomainMaxH(2, 0.02)\n",
    "ngmesh = geo.GenerateMesh(maxh=0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using lines and splines\n",
    "We define a new geometry and write a list of points we want to use for out geometry and add them to geo geometry."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "geo = SplineGeometry()\n",
    "\n",
    "pnts =[(0,0),\n",
    "       #(0,0,0.05), # define a local mesh refinement for one point\n",
    "       (1,0),\n",
    "       (1,0.5),\n",
    "       (1,1),\n",
    "       (0.5,1),\n",
    "       (0,1)]\n",
    "\n",
    "p1,p2,p3,p4,p5,p6 = [geo.AppendPoint(*pnt) for pnt in pnts]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then we define the curves which define our geometry and add them to the geometry using `Append`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3, 4]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "curves = [[[\"line\",p1,p2],\"bottom\"],\n",
    "          [[\"line\",p2,p3],\"right\"],\n",
    "          [[\"spline3\",p3,p4,p5],\"curve\"],\n",
    "          [[\"line\",p5,p6],\"top\"],\n",
    "          [[\"line\",p6,p1],\"left\"]]\n",
    "\n",
    "[geo.Append(c,bc=bc) for c,bc in curves]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "ngmesh = geo.GenerateMesh(maxh=0.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# from ngsolve import *\n",
    "# mesh = Mesh(ngmesh)\n",
    "# mesh.Curve(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Additonally to the boundary condition one can set a maximal mesh size for a whole curve with an optional argument `maxh`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "geo = SplineGeometry()\n",
    "\n",
    "p1,p2,p3,p4,p5,p6 = [geo.AppendPoint(*pnt) for pnt in pnts]\n",
    "\n",
    "geo.Append([\"line\",p1,p2],maxh=0.02)\n",
    "geo.Append([\"line\",p2,p4])\n",
    "geo.Append([\"line\",p4,p6])\n",
    "geo.Append([\"line\",p6,p1])\n",
    "\n",
    "ngmesh = geo.GenerateMesh(maxh=0.2)#,quad_dominated=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Periodic geometries\n",
    "The following example shows how construct a geometry for a periodic $L_2$ finite element space.\n",
    "\n",
    "Again we start with adding the points to the geometry. In this case the points of a hexagon. For the first three segments we save the return value (the line number) of `geo.Append`. Now we can use those line numbers to identify  each of the last three segments with the opposite, already added one. This identification is done with the optional argument `copy`. The meshing algorithm then just copies the boundary mesh to the opposite segment. Thus the segments have to have the same orientation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from math import pi, cos, sin\n",
    "geo = SplineGeometry()\n",
    "pnums = [ geo.AddPoint(cos(phi),sin(phi)) for phi in [x*pi/3 for x in range(6)] ]\n",
    "l1 = geo.Append([\"line\", 0, 1], leftdomain=1, rightdomain=0, bc=\"upperRight\")\n",
    "l2 = geo.Append([\"line\", 1, 2], leftdomain=1, rightdomain=0, bc=\"upperCenter\")\n",
    "l3 = geo.Append([\"line\", 2, 3], leftdomain=1, rightdomain=0, bc=\"upperLeft\")\n",
    "geo.Append([\"line\", 0, 5], leftdomain=0, rightdomain=1, bc=\"lowerRight\", copy = l3)\n",
    "geo.Append([\"line\", 5, 4], leftdomain=0, rightdomain=1, bc=\"lowerCenter\", copy = l2)\n",
    "geo.Append([\"line\", 4, 3], leftdomain=0, rightdomain=1, bc=\"lowerLeft\", copy = l1)\n",
    "ngmesh = geo.GenerateMesh(maxh=0.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
